import {
  db,
  definePlugin,
  Handler,
  NotFoundError,
  param,
  PERM,
  PermissionError,
  PRIV,
  Types,
} from "hydrooj";

const coll = db.collection("typepractice");

interface Typepractice {
  _id: string;
  owner: number;
  domainId: string;
  content: string;
  createtime: Date;
  speed: number;
  correct: number;
  error: number;
  charnums: number;
}

declare module "hydrooj" {
  interface Model {
    typepracticebin: typeof typepracticebinModel;
  }
  interface Collections {
    typepractice: Typepractice; // 声明数据表类型
  }
}

async function add(
  domainId: string,
  userId: number,
  content: string,
  speed: number,
  correct: number,
  error: number,
  charnums: number
): Promise<string> {
  const typepracticeId = String.random(16); // Hydro 提供了此方法，创建一个长度为16的随机字符串
  // 使用 mongodb 为数据库驱动，相关操作参照其文档
  const result = await coll.insertOne({
    _id: typepracticeId,
    domainId,
    owner: userId,
    content,
    createtime: new Date(),
    speed,
    correct,
    error,
    charnums,
  });
  return result.insertedId; // 返回插入的文档ID
}
async function get(typepracticeId: string): Promise<Typepractice> {
  return await coll.findOne({ _id: typepracticeId });
}

// 暴露这些接口，使得 cli 也能够正常调用这些函数；
const typepracticebinModel = { add, get };
global.Hydro.model.typepracticebin = typepracticebinModel;

// 创建新路由
class TypepracticeMainHandler extends Handler {
  // Get请求时触发该函数
  async get() {
    // 检查用户是否登录，此处为多余（因为底部注册路由时已声明所需权限）
    // 此方法适用于权限的动态检查
    // this.checkPriv(PRIV.PRIV_USER_PROFILE);
    this.response.template = "typepractice_main.html"; // 返回此页面
  }

  // 使用 Types.Content 检查输入
  @param("content", Types.Content)
  @param("speed", Types.Int)
  @param("correct", Types.Int)
  @param("error", Types.Int)
  @param("charnums", Types.Int)

  // 从用户提交的表单中取出content和private字段
  // domainId 为固定传入参数
  async post(
    domainId: string,
    speed: number,
    correct: number,
    error: number,
    charnums: number
  ) {
    // 在HTML表单提交的多选框中，选中值为 'on'，未选中则为空，需要进行转换
    const typepracticeid = await typepracticebinModel.add(
      domainId,
      this.user._id,
      "",
      speed,
      correct,
      error,
      charnums
    );
    // 将用户重定向到创建完成的url
    // // this.response.redirect = this.url("typepractice_main", {
    //   id: typepracticeid,
    // });
    this.back();
    // 相应的，提供了 this.back() 方法用于将用户重定向至前一个地址（通常用于 Ajax 或是部分更新操作）
  }
}

// Hydro会在服务初始化完成后调用该函数。
export async function apply(ctx) {
  // 注册一个名为 typepractice_create 的路由，匹配 '/typepractice/create'，
  // 使用TypepracticeCreateHandler处理，访问改路由需要PRIV.PRIV_USER_PROFILE权限
  // 提示：路由匹配基于 path-to-regexp
  ctx.Route(
    "typepractice_main",
    "/typepractice/main",
    TypepracticeMainHandler,
    PRIV.PRIV_USER_PROFILE
  );
  ctx.inject(
    "Nav",
    "typepractice_main",
    { prefix: "typepractice" },
    PERM.PERM_VIEW_PROBLEM
  );
  ctx.i18n.load("zh", {
    typepractice_main: "打字练习",
  });
}
